import Tween from "../anim/Tween";
import game from "../game";
import { Logger } from "../log/logger";
import Utils from "../utils/Utils";
import { SoundOption, SoundTypeOption } from "./SoundDefine";
import { SoundItem, soundMusic } from "./SoundItem";
import type SoundManage from "./SoundManage";

export class SoundTypeItem {

    private _items: SoundItem[] = [];

    /**是否激活 */
    private _active: boolean;

    /**类型 0背景音乐  */
    private _type: number;

    /**播放参数 */
    private _opt: SoundTypeOption;

    /**玩家自定义音量 */
    private _volume: number = 100;

    /**系统基础音量 */
    private _baseVolume: number = 100;

    /**压制系数，仅仅压制时候使用 */
    private _ratio: number = 100;

    /**上一次播放时间 */
    private _beforeTime: number = 0;

    constructor(type: number, opt: SoundTypeOption, private sm: SoundManage) {
        this._type = type;
        this._opt = opt;

        sm.on("active_changed"/* SoundManage.ACTIVE_CHANGED */, this, this.onActiveChanged);
    }

    play(url: string, param?: SoundOption) {

        //播放间隔限制
        if (game.saveTimeMs - this._beforeTime < this._opt.interval) {
            return;
        }

        let len = this._items.length;

        //最大发声数限制
        let isMax = len >= this._opt.max;
        if (isMax && !this._opt.replaceable) {

            Logger.logView("max sound limit", "sound");
            return;
        }

        //达到限制可替换
        if (isMax) {
            this._items.sort((a, b) => a.priority - b.priority);
            this._items.shift().stop();
        }

        let item = this._type === 0 ? soundMusic.create() : SoundItem.create(this._type);
        this.addItem(item);
        item.play(url, param);

        item.wait().then(() => this.removeItem(item), () => this.removeItem(item));

        return item;
    }

    stop(url?: string) {
        let items: SoundItem[] = [];
        for (let elm of this._items) {
            if (url === elm.url) {
                items.push(elm);
            }
        }
        items.forEach(v => v.stop());
    }

    stopAll() {
        this._items.forEach(v => v.stop());
    }

    updateVolume() {
        for (let elm of this._items) {
            elm.baseValume = this.volume;
        }
    }

    //设置基础音量与用户音量
    setVolume(base: number, use: number) {
        this._baseVolume = base;
        this._volume = use;
        this.updateVolume();
    }

    /**压制结束 */
    ratioStop(slow: boolean = false) {
        this.ratioVolume = 100;
    }

    addItem(item: SoundItem) {
        this._items.push(item);
        this.setActive(this._items.length > 0);
    }

    removeItem(item: SoundItem) {
        //TODO
        // this._items.remove(item);
        this.setActive(this._items.length > 0);
    }


    /**基础音量 */
    public get volume() {
        return Utils.lerpScale(this._baseVolume, 100, this._opt.volume, this._volume, this._ratio);
    }

    public resetRatio() {
        this._ratio = 100;
        this.updateVolume();
    }

    /**设置压制系数 */
    public set ratioVolume(v: number) {
        this._ratio = v;
        this.updateVolume();
    }

    public set volueByUI(v: number) {
        if (v != this._volume) {
            this._volume = v;
            this.updateVolume();
        }
    }

    /**UI显示音量，用于用户控制 */
    public get volueByUI() {
        return this._volume;
    }

    public get active() {
        return this._active;
    }

    get baseVolume() {
        return this._baseVolume || 100;
    }

    set baseVolume(v: number) {
        this._baseVolume = v;

        this.updateVolume();
    }

    get useVolume() {
        return this._volume;
    }

    set useVolume(v: number) {
        this._volume = v;
    }

    private onActiveChanged(type: number) {
        if (type === this._type) {
            return;
        }

        let opt = this._opt;
        if (!opt || !opt.supresses || opt.supresses.length <= 0) {
            return;
        }

        let supresses = opt.supresses.find(supress => supress.type === type);
        if (!supresses) {
            return;
        }

        //被该类型压制
        let item = this.sm.getItem(type);
        if (!item) {
            return;
        }

        Tween.clear(this);
        if (item.active) {
            let value = supresses.ratio;
            Tween.get<SoundTypeItem>(this).to({ ratioVolume: value }, supresses.attackTime)
        } else {
            Tween.get<SoundTypeItem>(this).to({ ratioVolume: 100 }, supresses.releaseTime)
        }

    }

    private setActive(v: boolean) {
        if (v === this._active) return;
        this._active = v;

        this.sm.event("active_changed"/* SoundManage.ACTIVE_CHANGED */, this._type);
    }
}